import uuid
from decimal import Decimal
from typing import Optional, Dict, Any

import pandas as pd

from src.core.strategy.stop_loss.stop_loss_manager import StopLossManager
from src.core.strategy.take_profit.take_profit_manager import TakeProfitManager
# 导入框架的依赖
from src.enums.enums import Direction, PositionStatus


class Position:
    """
    一个自包含的、高精度的仓位数据模型。

    它代表了一笔独立的交易（无论是初次建仓还是后续的加仓），
    并负责跟踪该笔交易从开仓到平仓的整个生命周期内的所有状态和数据。
    """

    def __init__(
            self,
            symbol: str,
            direction: Direction,
            quantity: Decimal,
            entry_price: Decimal,
            entry_time: pd.Timestamp,
            margin: Decimal,
            open_fee: Decimal,
            stop_loss_manager: Optional[StopLossManager] = None,
            take_profit_manager: Optional[TakeProfitManager] = None,
            metadata: Optional[Dict[str, Any]] = None
    ):
        """
        在开仓时由Portfolio创建。

        Args:
            symbol (str): 交易对, e.g., "ETHUSDT"。
            direction (Direction): 交易方向, LONG 或 SHORT。
            quantity (Decimal): 仓位数量 (已做精度对齐)。
            entry_price (Decimal): 开仓成交价 (已做精度对齐)。
            entry_time (pd.Timestamp): 开仓时间。
            margin (Decimal): 此仓位占用的保证金。
            open_fee (Decimal): 开仓时产生的手续费。
            stop_loss_manager (Optional[IStopLossManager]): 与此仓位绑定的止损管理器实例。
            take_profit_manager (Optional[ITakeProfitManager]): 与此仓位绑定的止盈管理器实例。
            metadata (Optional[Dict[str, Any]]): 
                与开仓相关的元数据, e.g., {'reason': 'MA Golden Cross'}。
        """
        # --- 唯一标识符 ---
        self.id: str = uuid.uuid4().hex

        # --- 核心仓位属性 ---
        self.symbol = symbol
        self.direction = direction
        self.quantity = quantity
        self.entry_price = entry_price

        # --- 状态与时间 ---
        self.status: PositionStatus = PositionStatus.OPEN
        self.entry_time = entry_time
        self.close_time: Optional[pd.Timestamp] = None

        # --- 保证金与费用 (Decimal) ---
        self.margin = margin
        self.open_fee = open_fee
        self.close_fee: Decimal = Decimal('0')

        # --- 盈亏跟踪 (Decimal) ---
        # 实时浮动盈亏，会随市价不断变化
        self.unrealized_pnl: Decimal = Decimal('0')

        # 持仓期间达到的最高浮动盈利，用于计算持仓利润回撤
        self.highest_pnl_in_position: Decimal = Decimal('0')

        # 平仓后最终的净盈亏 (Gross PnL - Total Fees)
        self.net_pnl: Decimal = Decimal('0')
        # 平仓后最终的毛盈亏 (不含手续费)
        self.gross_pnl: Decimal = Decimal('0')

        # --- 平仓信息 ---
        self.exit_price: Optional[Decimal] = None
        self.exit_reason: Optional[str] = None

        # --- 注入的组件 ---
        self.stop_loss_manager = stop_loss_manager
        self.take_profit_manager = take_profit_manager

        # --- 附加信息 ---
        self.metadata = metadata if metadata is not None else {}

    def is_long(self) -> bool:
        """检查仓位是否为多头。"""
        return self.direction == Direction.LONG

    def is_short(self) -> bool:
        """检查仓位是否为空头。"""
        return self.direction == Direction.SHORT

    def get_opposite_direction(self) -> Direction:
        """获取与当前仓位相反的方向。"""
        return Direction.SHORT if self.is_long() else Direction.LONG

    def update_market_price(self, current_price: Decimal):
        """
        【实时调用】由Portfolio在每个时间点调用，以更新浮动盈亏。
        """
        if self.status != PositionStatus.OPEN:
            return

        # 计算毛的浮动盈亏
        price_diff = current_price - self.entry_price
        if self.is_short():
            price_diff = -price_diff

        gross_unrealized_pnl = price_diff * self.quantity

        # 净的浮动盈亏需要考虑已支付的开仓手续费
        self.unrealized_pnl = gross_unrealized_pnl - self.open_fee

        # 更新持仓期间的最高浮动盈利
        if self.unrealized_pnl > self.highest_pnl_in_position:
            self.highest_pnl_in_position = self.unrealized_pnl

    def close(self, exit_price: Decimal, exit_time: pd.Timestamp, close_fee: Decimal, reason: str = ''):
        """
        【平仓时调用】由Portfolio调用，以最终确定仓位的所有状态。
        """
        if self.status != PositionStatus.OPEN:
            print(f"WARNING: 尝试关闭一个已经关闭的仓位 (ID: {self.id})。")
            return

        # 1. 更新状态和时间
        self.status = PositionStatus.CLOSED
        self.close_time = exit_time
        self.exit_price = exit_price
        self.exit_reason = reason

        # 2. 记录平仓手续费
        self.close_fee = close_fee

        # 3. 最终确定所有盈亏值
        #   a. 计算毛盈亏
        price_diff = self.exit_price - self.entry_price
        if self.is_short():
            price_diff = -price_diff
        self.gross_pnl = price_diff * self.quantity

        #   b. 计算净盈亏
        total_fees = self.open_fee + self.close_fee
        self.net_pnl = self.gross_pnl - total_fees

        #   c. 仓位关闭后，浮动盈亏归零
        self.unrealized_pnl = Decimal('0')

    def __repr__(self) -> str:
        """提供一个清晰的字符串表示，方便调试。"""
        pnl_str = f"Net PnL: {self.net_pnl:.4f}" \
            if self.status == PositionStatus.CLOSED else f"Unrealized PnL: {self.unrealized_pnl:.4f}"
        return (
            f"Position(id={self.id[:8]}, status={self.status.name}, "
            f"symbol={self.symbol}, dir={self.direction.name}, "
            f"qty={self.quantity}, entry_price={self.entry_price}, "
            f"{pnl_str})"
        )
